////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2017 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file camxthreadjoblist.cpp
///
/// @brief Provides container for runtime jobs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "camxincs.h"
#include "camxthreadjoblist.h"

CAMX_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JobList::JobList
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
JobList::JobList(
    JobRegistry* pJobRegistry)
    : m_pJobRegistry(pJobRegistry)
    , m_freeTail(MaxRuntimeJobs - 1)
{
    UINT32 i = 0;

    for (i = 0; i < MaxRuntimeJobs; i++)
    {
        m_freeList[i].slot = i;
        m_freeList[i].next = i + 1;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JobList::~JobList
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
JobList::~JobList()
{
    if (NULL != m_pListLock)
    {
        m_pListLock->Destroy();
        m_pListLock = NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JobList::Initialize
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult JobList::Initialize()
{
    CamxResult result = CamxResultSuccess;

    m_pListLock = Mutex::Create("JobList");
    if (NULL == m_pListLock)
    {
        CAMX_LOG_ERROR(CamxLogGroupUtils, "Couldn't create lock resources");
        result = CamxResultEFailed;
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JobList::AcquireJobEntry
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RuntimeJob* JobList::AcquireJobEntry(
    JobHandle hJob)
{
    RuntimeJob* pRuntimeJob = NULL;

    CAMX_ASSERT(m_pListLock != NULL);

    m_pListLock->Lock();

    if (m_freeHead != m_freeTail)
    {
        pRuntimeJob       = &m_jobList[m_freeHead];
        pRuntimeJob->slot = m_freeHead;
        m_freeHead = m_freeList[m_freeHead].next;

        m_jobOccupancy++;

        m_pJobRegistry->IncrementJobCount(hJob);
    }

    m_pListLock->Unlock();

    return pRuntimeJob;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// JobList::ReleaseJobEntry
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID JobList::ReleaseJobEntry(
    RuntimeJob* pJob)
{
    CAMX_ASSERT(pJob != NULL);
    CAMX_ASSERT(m_pListLock != NULL);

    m_pListLock->Lock();

    m_freeList[m_freeTail].next = pJob->slot;
    m_freeTail = pJob->slot;
    m_jobOccupancy--;

    if (m_pJobRegistry->GetJobCount(pJob->hJob))
    {
        m_pJobRegistry->DecrementJobCount(pJob->hJob);
    }

    m_pListLock->Unlock();
}

CAMX_NAMESPACE_END
